{-# LANGUAGE ScopedTypeVariables        #-}


module DemoNew where

import Orca.Csound.Monad
import Orca.Csound.Syntax
import Orca.Csound.SignalGenerators
import Orca.Csound.SignalIO
import Orca.Csound.SignalModifiers
import Orca.Csound.Zak
import Orca.Toplevel.Monad


import Control.Applicative

demo01 = ppStmts $ execOrca $ do 
  asig1 :: ASig <- oscilA (440.0 :: ASig) 
  asig2 <- oscilA (440.0 :: ASig) :: Orca ASig
  isig3 <- pureE $ castI $ asig1 + asig2                -- nonsense... but still
  cs_out (castA isig3)



demo02 = ppStmts $ execCode () code
  where
    code :: Code () ()
    code = do 
        asig1 <- liftOrca (oscilA a440)
        liftOrca $ cs_out asig1




-- Are there valid signal transformer functions?
-- Sig rate -> Sig rate


-- Remember @before and @after methods ala CLOS
-- 
-- Before and after have to be explicit in a record 
-- (BellRegistry)

data BellHooks = M1 | M2 | M3 | M4 | C1 | C2 | C3 
  deriving (Enum,Eq,Ord,Show)

data BellRegistry ctx = BellRegistry 
    { m1_transform :: SigTrans ctx ARate
    }

defaultBellRegistry :: BellRegistry ctx
defaultBellRegistry = BellRegistry
    { m1_transform = return
    }

type BellAlgo ctx a = Algo (BellRegistry ctx) ctx a

dummy :: Get_isine_table ctx => ASig -> BellAlgo ctx ASig
dummy insig = do 
   asig1 <- operator1 m1_transform fmphasor insig
   return asig1

kindxenv :: Get_iduration ctx => SigGen ctx KRate  
kindxenv = expseg $ \idur -> 
    return ( 1.0, [ idur ::: 0.01 ])

kampenv :: Get_iduration ctx => SigGen ctx KRate  
kampenv = expseg $ \idur -> 
    return ( 0.01, [ 0.002        ::: 1
                   , idur - 0.002 ::: 0.01
                   ])

data FMBellAlgo ctx = FMBellAlgo
    { m1_postpro        :: SigTrans ctx ARate
    , m2_postpro        :: SigTrans ctx ARate
    , m3_postpro        :: SigTrans ctx ARate
    , m2_m3_envelope    :: SigTrans ctx ARate
    , m4_postpro        :: SigTrans ctx ARate
    , c1_postpro        :: SigTrans ctx ARate
    , c2_postpro        :: SigTrans ctx ARate
    , c3_postpro        :: SigTrans ctx ARate
    , out_envelope      :: SigTrans ctx ARate

    }


fmBell2 mod1freq mod2freq mod3freq mod4freq car1freq car2freq car3freq = do
    amod1sig       <- liftSigGen $ fmphasor (castA mod1freq)
    amod1dev       <- apply1 m1_postpro amod1sig

    acar1sig_      <- liftSigGen $ fmphasor (car1freq .+. amod1dev)
    acar1sig       <- apply1 c1_postpro acar1sig_

    amod2sig       <- liftSigGen $ fmphasor (castA mod2freq)
    amod2dev       <- apply1 m2_postpro amod2sig

    amod3sig       <- liftSigGen $ fmphasor (castA mod3freq)
    amod3dev       <- apply1 m3_postpro amod3sig

    am2_m3_dev     <- apply1 m2_m3_envelope (amod2dev + amod3dev)

    acar2sig_      <- liftSigGen $ fmphasor (car2freq .+. am2_m3_dev)
    acar2sig       <- apply1 c1_postpro acar2sig_

    amod4sig       <- liftSigGen $ fmphasor (castA mod4freq)
    amod4dev       <- apply1 m4_postpro amod4sig

    acar3sig_      <- liftSigGen $ fmphasor (car3freq .+. amod4dev)
    acar3sig       <- apply1 c1_postpro acar3sig_

    aout           <- apply1 out_envelope (acar1sig + acar2sig + acar3sig)

    return acar2sig



-- This is prior to Algorithm style
fmBell mod1in dummysig = do 
    -- modulator 1   
    amod1sig        <- fmphasor mod1in
    
    -- carrier 1 
    acar1sig        <- fmphasor amod1sig

    -- modulator 2
    amod2sig        <- fmphasor dummysig

    -- modulator 3
    amod3sig        <- fmphasor dummysig

    -- What to do for signal summation?
    amod2_3sig      <- liftOrca $ pureE $ amod2sig + amod3sig

    -- carrier 2
    acar2sig        <- fmphasor amod2_3sig

    -- modulator 4
    amod4sig        <- fmphasor dummysig

    -- carrier 3
    acar3sig        <- fmphasor amod4sig

    -- ditto - more summation here
    aout            <- liftOrca $ pureE $ acar1sig + acar2sig + acar3sig

    return aout


---

a440 :: ASig
a440 = PExpr $ Value A_RATE $ Float 440.0


oscilA :: ASig -> Orca ASig
oscilA sig = genOpcode1 A_RATE "oscil" [getPExpr sig]

